using System.Collections;
using RomanJendrusz.Amazon.ETL.Infrastructure.IoC;
using RomanJendrusz.Amazon.ETL.Repositories;
using RomanJendrusz.Amazon.ETL.Tasks;
using RomanJendrusz.Amazon.ETL.Infrastructure.Loging.Core;
using System.Collections.Generic;
using RomanJendrusz.Amazon.ETL.Domain;
using System;

namespace RomanJendrusz.Amazon.ETL.Strategies
{
    public class SimiliarBookRetrievalStrategy: IDataRetrievalStrategy
    {
        private readonly IUnitOfWorkFactory unitOfWorkFactory;
        private BookTask bookTask;
        private CustomerReviewTask reviewsTask;
        private SellerOfferTask sellerOfferTask;

        public SimiliarBookRetrievalStrategy(IUnitOfWorkFactory unitOfWorkFactory)
        {
            this.unitOfWorkFactory = unitOfWorkFactory;
        }

        public void RetrieveBy(params string[] isbns)
        {
            using (var work = unitOfWorkFactory.BeginUnitOfWork())
            {
                var arguments = new Hashtable { { "unitOfWork", work } };
                bookTask = IoCGateway.Resolve<BookTask>(arguments);
                sellerOfferTask = IoCGateway.Resolve<SellerOfferTask>(arguments);
                reviewsTask = IoCGateway.Resolve<CustomerReviewTask>(arguments);
                foreach (var isbn in isbns)
                {
                        LogGateway.LogFor(GetType()).Warn("Running Similiar Book Retrieval Strategy for book with ISBN " + isbn);
                        var book = bookTask.RetrieveBookBy(isbn);
                        bookTask.RetrieveBrowseNodesFor(book);
                        reviewsTask.RetrieveReviewsFor(book);
                        //sellerOfferTask.RetrieveSellerOffersFor(book);
                        retrieveHierarchyOfSimiliarBooksFor(book, AmazonConstants.SimilarBooksHierarchyDepth);   
                }
            }   
        }

        private void retrieveHierarchyOfSimiliarBooksFor(Book book, int depth)
        {
            if (book == null)
            {
                return;
            }
            if (depth < 0)
            {
                throw new ArgumentOutOfRangeException("depth", "Depth can't be less than 0");
            }
            LogGateway.LogFor(GetType()).Warn(string.Format(
                                                  "Retrieving similiar books for book with asin {0} and title {1}",
                                                  book.Asin, book.Title));
            IList<SimiliarBook> similiarBooks = bookTask.RetrieveSimiliarBooksFor(book);
            if(similiarBooks != null)
            {
                foreach (var similiarity in similiarBooks)
                {
                    bookTask.RetrieveBrowseNodesFor(similiarity.BooksSimiliarTo);
                    Book similiarBook = similiarity.BooksSimiliarTo;
                    reviewsTask.RetrieveReviewsFor(similiarBook);
                    //sellerOfferTask.RetrieveSellerOffersFor(similiarBook);
                }
            }
            if (depth == 0)
            {
                return;
            }
            if (similiarBooks == null)
            {
                return;
            }
            foreach (SimiliarBook similiarBook in similiarBooks)
            {
                retrieveHierarchyOfSimiliarBooksFor(similiarBook.BooksSimiliarTo, depth - 1);
            }
        }
    }
}